import * as fs from 'node:fs'
import * as path from 'node:path'
import { commonInfo, description } from './common'

export function makeModule(folderPath: string): void {
    try {
        const moduleJsonPath = path.join(folderPath, 'entry', 'src', 'main', 'module.json')
        const moduleJsonStr = fs.readFileSync(moduleJsonPath, { encoding: 'utf8', flag: 'r' })
        const moduleJson = JSON.parse(moduleJsonStr)
        const moduleJson5 = {
            module: {
                name: 'entry',
                type: 'entry',
                srcEntry: './ets/Application/AbilityStage.ts',
                description: moduleJson.module?.description ?? 'TODO',
                mainElement: 'EntryAbility',
                deviceTypes: moduleJson.module?.deviceTypes?.filter?.((item: string) => item !== 'phone') ?? [
                    'default',
                    'tablet',
                    '2in1',
                    'wearable'
                ],
                deliveryWithInstall: moduleJson.module?.deliveryWithInstall,
                installationFree: moduleJson.module?.installationFree,
                pages: moduleJson.module?.pages ?? 'TODO',
                metadata: moduleJson.module?.metadata,
                abilities: [{
                    name: `${commonInfo.bundleName ?? 'ERROR_NO_BUNDLE_NAME'}.EntryAbility`,
                    srcEntry: './ets/entryability/EntryAbility.ets',
                    description: moduleJson.module?.abilities?.[0]?.description ?? 'TODO',
                    icon: moduleJson.module?.abilities?.[0]?.icon ?? 'TODO',
                    label: moduleJson.module?.abilities?.[0]?.label ?? 'TODO',
                    startWindowIcon: moduleJson.module?.abilities?.[0]?.startWindowIcon
                        ?? moduleJson.module?.abilities?.[0]?.icon ?? 'TODO',
                    startWindowBackground: moduleJson.module?.abilities?.[0]?.startWindowBackground
                        ?? '$color:start_window_background',
                    exported: moduleJson.module?.abilities?.[0]?.visible,
                    orientation: moduleJson.module?.abilities?.[0]?.orientation,
                    skills: moduleJson.module?.abilities?.[0]?.skills ?? [{
                        entities: ['entity.system.home'],
                        actions: ['action.system.home']
                    }],
                }],
                requestPermissions: moduleJson.module?.requestPermissions !== undefined
                    ? JSON.parse(
                        JSON.stringify(moduleJson.module.requestPermissions)?.replace(
                            /"\w*Ability"/i, '"EntryAbility"'
                        )
                    ) ?? "TODO"
                    : undefined
            }
        }
        delete moduleJson.module?.srcEntrance
        delete moduleJson.module?.deviceTypes
        delete moduleJson.module?.uiSyntax
        delete moduleJson.module?.abilities?.[0]?.srcEntrance
        delete moduleJson.module?.abilities?.[0]?.visible
        copyOtherFields(moduleJson5, moduleJson)
        const moduleJson5Str = JSON.stringify(moduleJson5, null, 2)
        const todoFieldsCounter = moduleJson5Str.match(/TODO/g)?.length ?? 0
        if (todoFieldsCounter > 0) {
            console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
            console.warn('\x1b[33m%s\x1b[0m', `WARNING main/module.json5 has unresolved fields. Please check TODO in module.json5.`)
            console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
        }
        fs.writeFileSync(path.join(folderPath, 'entry', 'src', 'main', 'module.json5'),
                description + '\n' + moduleJson5Str, 'utf8')
        fs.unlinkSync(moduleJsonPath)

        const colorJsonPath = path.join(folderPath, 'entry', 'src', 'main', 'resources', 'base', 'element', 'color.json')
        const colorValue = {
            name: moduleJson5.module.abilities[0].startWindowBackground.slice?.(7),
            value: '#FFFFFF'
        }
        if (fs.existsSync(colorJsonPath)) {
            const colorJsonStr = fs.readFileSync(colorJsonPath, { encoding: 'utf8', flag: 'r' })
            if (colorJsonStr.indexOf(colorValue.name) < 0) {
                const colorJson = JSON.parse(colorJsonStr)
                colorJson.color = (colorJson.color || []).push?.(colorValue)
                fs.writeFileSync(colorJsonPath, JSON.stringify(colorJson, null, 2))
            }
        } else {
            fs.writeFileSync(colorJsonPath, JSON.stringify({
                color: [colorValue]
            }, null, 2))
        }
    } catch (err) {
        console.error('Error: ' + err)
        console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
        console.warn('\x1b[33m%s\x1b[0m', `WARNING main/module.json5 is not created. Please add module.json5 manually.`)
        console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
    }
}

function copyOtherFields(dstObject: any, srcObject: any) {
    for (const key in srcObject) {
        if (isObjects(dstObject[key], srcObject[key])) {
            if (Array.isArray(srcObject[key])) {
                if (dstObject[key] === undefined) {
                    dstObject[key] = []
                }
                if (Array.isArray(dstObject[key])) {
                    copyOtherArrayFields(dstObject[key], srcObject[key])
                }
            } else {
                copyOtherFields(dstObject[key], srcObject[key])
            }
        } else if (dstObject[key] === undefined) {
            dstObject['TODO >>> ' + key] = srcObject[key]
        }
    }
}

function copyOtherArrayFields(dstArr: any[], srcArr: any[]) {
    for (let i = 0; i < srcArr.length; ++i) {
        if (i < dstArr.length) {
            if (isObjects(dstArr[i], srcArr[i])) {
                if (Array.isArray(srcArr[i])) {
                    if (dstArr[i] === undefined) {
                        dstArr[i] = []
                    }
                    if (Array.isArray(dstArr[i])) {
                        copyOtherArrayFields(dstArr[i], srcArr[i])
                    }
                } else {
                    copyOtherFields(dstArr[i], srcArr[i])
                }
            } else if (dstArr[i] === undefined) {
                dstArr = [...srcArr.splice(0, i), "TODO ^^^ see previous item", ...srcArr.splice(i)]
            }
        } else {
            dstArr.push(srcArr[i], "TODO ^^^ see previous item")
        }
    }
}

function isObjects(...arr: any[]) {
    return arr.every(v => typeof v === 'object')
}
